#include "digital_tube.h"

/**
 * @brief 共阴字库
 */
const static uint8_t common_cathode_lib[] = {
    0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0xfe, 0xf6, // 0 ~ 9
    0xee, 0x3e, 0x9c, 0x7a, 0x9e, 0x8e,                         // A ~ F
    0x01, 0x00, 0x02,                                           // DP 空 -
};

// 遍历数码管位列表，选中当前位
void __DIGITAL_TUBE_SET_BIT_FOREACH(digital_tube_bits digital_tube_bit)
{
    digital_tube_bits i;
    for (i = 0; i < DIGITAL_TUBE_BIT_MAX; i++)
    {
#define CHOOSE(bit)                                               \
    case bit:                                                     \
        __DIGITAL_TUBE_CHOOSE_BIT(bit, !(i == digital_tube_bit)); \
        break

        switch (i)
        {
            CHOOSE(SMG_BIT_1);
            CHOOSE(SMG_BIT_2);
            // CHOOSE(SMG_BIT_3);
            // CHOOSE(SMG_BIT_4);
        default:
            break;
        }
    }
}

#if __DIGITAL_TUBE_HC138
/**
 * @brief 138：数码管位选：A2 A1 A0
 *        2^3 = 8 => { 0 ~ 7 ：数码管的第1位到第8位 }
 * @param bit 位
 */
static void __DIGITAL_TUBE_SET_BIT_HC138(uint8_t bit)
{
    // 假设当前选中第 4 位
    // 位    2   1   0
    //      A2  A1  A0
    //       1   0   0
    if (bit > DIGITAL_TUBE_BIT_MAX)
        return;
    __DIGITAL_TUBE_HC138_A0((bit >> 0) & 0x01);
    __DIGITAL_TUBE_HC138_A1((bit >> 1) & 0x01);
    __DIGITAL_TUBE_HC138_A2((bit >> 2) & 0x01);
}
#endif

void digital_tube_set_bit(uint8_t seg, uint8_t bit)
{
    uint8_t i;
    uint8_t asc = common_cathode_lib[seg]; // 从当前数组取出数码管字符 0->'0x3F'
    __DIGITAL_TUBE_LCLK(0);
    // 1.数码管段选
    for (i = 0; i < 8; i++) // 发送8个位的数据，低位开始发，串行通信
    {
        // 1.先送数据按位送到到‘DATA’的数据线上
        __DIGITAL_TUBE_DATA((asc >> i) & 0x01);
        // 2.SCLK给一个上升沿电平触发
        //        ___
        //    __| ↑
        __DIGITAL_TUBE_SCLK(0);
        __DIGITAL_TUBE_DELAY();
        __DIGITAL_TUBE_SCLK(1);
    }
    // 2.触发输出:LCLK给一个高电平触发数码管输出
    __DIGITAL_TUBE_LCLK(1);
    // 3.后位选
#if __DIGITAL_TUBE_HC138
    __DIGITAL_TUBE_SET_BIT_HC138(bit);
#else
    __DIGITAL_TUBE_SET_BIT_FOREACH(bit);
#endif

}

void digital_tube_init(void)
{
    // 位选清空
#if __DIGITAL_TUBE_HC138
    __DIGITAL_TUBE_HC138_A0(bit, 0);
    __DIGITAL_TUBE_HC138_A1(bit, 0);
    __DIGITAL_TUBE_HC138_A2(bit, 0);
#else
    __DIGITAL_TUBE_CHOOSE_BIT(SMG_BIT_1, 1);
    __DIGITAL_TUBE_CHOOSE_BIT(SMG_BIT_2, 1);
#endif
    // 段选清空
    __DIGITAL_TUBE_DATA(0);
    __DIGITAL_TUBE_LCLK(0);
    __DIGITAL_TUBE_SCLK(0);
}

void digital_tube_clean()
{
    uint8_t i;
    for (i = 0; i < DIGITAL_TUBE_BIT_MAX; i++)
    {
        digital_tube_set_bit(DIGITAL_TUBE_NONE, i);
        __DIGITAL_TUBE_DELAY();
    }
}